Type GUI_PolledInput

	Global instance:GUI_PolledInput

	Field suspended:Int
	Field terminate:Int
	Field keyStates:Int[256]
	Field keyHits:Int[256]
	Field keyHitCheck:Int[256]
	Field mouseStates:Int[4]
	Field mouseHits:Int[4]
	Field mouseHitCheck:Int[4]
	Field mouseLocation:Int[3]
	
	Function GetInstance:GUI_PolledInput()
		If instance = Null Then
			instance = New GUI_PolledInput
			instance.FlushKeys()
			instance.FlushMouse()
			AddHook(EmitEventHook, Hook, instance, 0)
		End If
		Return instance
	End Function
	
	Function Hook:Object(id:Int, data:Object, context:Object)
		Local pInput:GUI_PolledInput = GUI_PolledInput(context)
		If Not pInput Then
			Return data
		End If
		Local ev:TEvent=TEvent(data)
		If Not ev Return data		
		Select ev.id
			Case EVENT_KEYDOWN
				If Not pInput.keyStates[ev.data]
					pInput.keyStates[ev.data] = 1
					pInput.keyHits[ev.data]:+ 1
				EndIf
			Case EVENT_KEYUP
				pInput.keyStates[ev.data] = 0
			Case EVENT_MOUSEDOWN
				If Not pInput.mouseStates[ev.data]
					pInput.mouseStates[ev.data] = 1
					pInput.mouseHits[ev.data]:+ 1
				EndIf
			Case EVENT_MOUSEUP
				pInput.mouseStates[ev.data] = 0
			Case EVENT_MOUSEMOVE
				pInput.mouseLocation[0] = ev.x
				pInput.mouseLocation[1] = ev.y
			Case EVENT_MOUSEWHEEL
				pInput.mouseLocation[2]:+ ev.data
			Case EVENT_APPSUSPEND
				pInput.FlushKeys()
				pInput.FlushMouse()
				pInput.suspended = True
			Case EVENT_APPRESUME
				pInput.FlushKeys()
				pInput.FlushMouse()
				pInput.suspended = False
			Case EVENT_APPTERMINATE
				pInput.terminate = True
		End Select
		Return data
	End Function
	
	Method Poll()
		Local i:Byte
		For i=0 Until 256
			If keyHitCheck[i] = 1 Then
				keyHits[i]     = 0
				keyHitCheck[i] = 0
			End If
		Next
		For i=0 Until 4
			If mouseHitCheck[i] = 1 Then
				mouseHits[i]     = 0
				mouseHitCheck[i] = 0
			End If
		Next
		PollSystem()
	End Method
	
	Method AppSuspended:Int()
		Return suspended
	End Method
	
	Method AppTerminate:Int()
		Return terminate
	End Method
	
	Method FlushKeys()
		For Local i:Byte=0 Until 256
			keyStates[i]   = 0
			keyHits[i]     = 0
			keyHitCheck[i] = 0
		Next
	End Method
	
	Method KeyHit:Int( key:Byte )
		keyHitCheck[key]=1
		Return keyHits[key]
	End Method
	
	Method KeyDown:Int( key:Byte )
		Return keyStates[key]
	End Method
	
	Method SetKeyHit(key:Byte, value:Int)
		keyHits[key] = value
	End Method
	
	Method SetKeyDown(key:Byte, value:Byte)
		If value > 0 Then
			keyStates[key] = 1
		Else
			keyStates[key] = 0
		End If
	End Method
	
	Method FlushMouse()
		For Local i:Byte=0 Until 4
			mouseStates[i] = 0
			mouseHits[i]   = 0
		Next
		mouseLocation[2] = 0
	End Method
	
	Method MouseX:Int()
		Return mouseLocation[0]
	End Method

	Method MouseY:Int()
		Return mouseLocation[1]
	End Method

	Method MouseZ:Int()
		Return mouseLocation[2]
	End Method
	
	Method MouseHit:Int( button:Byte )
		mouseHitCheck[button] = 1
		Return mouseHits[button]
	End Method

	Method MouseDown:Int( button:Byte )
		Return mouseStates[button]
	End Method
	
	Method SetMouseX(value:Int)
		mouseLocation[0] = value
	End Method

	Method SetMouseY(value:Int)
		mouseLocation[1] = value
	End Method

	Method SetMouseZ(value:Int)
		mouseLocation[2] = value
	End Method
	
	Method SetMouseHit( button:Byte, value:Int )
		mouseHits[button] = value
	End Method

	Method SetMouseDown( button:Byte, value:Byte )
		If value > 0 Then
			mouseStates[button] = 1
		Else
			mouseStates[button] = 0
		End If
	End Method

End Type
